#ifndef HEAD_H
#define HEAD_H
//服务器头文件
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <time.h>
#include <sys/wait.h>
#include <dirent.h>
#include <syslog.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <signal.h>
#include <sys/time.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/epoll.h>
#include <sys/sendfile.h>
#include <mysql/mysql.h>
#define ARGS_CHECK(argc, expected)\
    do {\
        if ((argc) != (expected)) {\
            fprintf(stderr, "args num error!\n");\
	    exit(1);\
        }\
    } while (0)                      

#define ERROR_CHECK(ret, error_flag, msg)\
    do {\
        if ((ret) == (error_flag)) {\
            perror(msg);\
            exit(1);\
        }\
    } while (0)

#define THREAD_ERROR_CHECK(ret,msg) {if(ret!=0){fprintf(stderr,"%s:%s\n",msg,strerror(ret));}}
 

enum command {
    client_exit = -1,
    ls = 0,
    cd = 1,
    pwd = 2,//虽然服务器不需要处理pwd命令，但是为了避免和客户端的定义混淆，此处也占用一位；
    upload = 3,
    download = 4,
    rm = 5,
    cdir = 6
};

typedef struct train 
{
  enum command op;
  char path[200];
}train_t;

//队列元素结点类型 node_t
typedef struct session_node{
    int net_fd;
    struct session_node *pnext;
}node_t;


//队列结构体类型 queue_t
typedef struct session_queue{
    int queue_size;
    node_t *head;
    node_t *tail;
}queue_t;

typedef struct thread_poll_s{
    pthread_t *tids;
    int thread_num;
    queue_t sessions;
    pthread_mutex_t lock;
    pthread_cond_t cond;
    int exit_flag;
}thread_poll;

typedef struct user_s{
    int flag;
    char user_name[100];
    char password[100];
}user;

int read_config(const char* config_file_path,char* port ,char* ip);

int server_login(int client_fd,char* cur_path);

int initThreadPoll(thread_poll* poll, int num);//初始化线程池

//入队函数
int enqueue(int client_fd, queue_t *queue);

//出队函数 返回值为出队元素，即客户端通信socket文件描述符
int dequeue(queue_t *queue); //deQueue返回出队的client_fd

int initTcpLink(int *socket_fd,char *ip,char *port);

int addtoEpoll(int epoll_fd, int socket_fd);
int delfromEpoll(int epoll_fd, int socket_fd);

void* threadMain(void *p); //子进程主函数

//flag为0表示正常进行cd操作
//flag为1表示rm调用进行cd操作
int server_cd(int client_fd,char* cmd_argv,char* cur_path);
int server_ls(int client_fd,char* cur_path);
int server_upload(int client_fd,char* cmd_argv,char *cur_path);//接收文件，参数名cmd_argv为客户端上传的参数，创建文件的路径为cur_path;
int server_download(int client_fd,char* cmd_argv,char*cur_path);
int server_rm(int client_fd,char *cmd_argv,char*cur_path);
int server_cdir(int client_fd, char*cmd_argv,char*cur_path);


#endif

